//数据库操作文件
//model生成的User实例，可以直接对mongodb操作
const {
  User,
  Friend,
  Group,
  GroupUser,
  Message,
  GroupMessage,
} = require("../model/dbmodel");
const os=require('os');
const bcrypt = require("./bcrypt"),
  jwt = require("./jwt");
//新建用户函数
exports.buildUser = (name, mail, pwd, res) => {
  // 先判断用户是否已经存在 不需要判断用户名
  let wherestr = { $or: [{ email: mail }] };
  User.countDocuments(wherestr, (err, result) => {
    if (result) {
      res.send({ status: 300 });
    } else {
      // 密码加密
      let password = bcrypt.encryption(pwd);
      // 新建一个document，然后方便model的insert
      //字段需要和schema映射一直
      let data = {
        name: name,
        email: mail,
        psw: password,
        //注册时间
        time: new Date(),
      };
      //按照User model新建一条数据
      let user = new User(data);
      //save存在数据库中
      user.save((err, result) => {
        if (err) {
          res.send({ status: 500 });
        } else {
          res.send({ status: 200 });
        }
      });
    }
  });
};


//验证邮箱和姓名是否重复 也许你可以注意一下这个res 用来返回前端你的数据
exports.CountUserValue = (data, type, res) => {
  //json对象
  let wherestr = {};
  //可能有问题
  // if(!data.length){
  //    // res.send({status:500})
  //    wherestr[type]='null表示不存在这个人，因为传入的data是空，又不能提前返回'
  // }
  wherestr[type] = data;
  // console.log(wherestr,'wherestr');
  //匹配元素个数，匹配参数，匹配结果
  User.countDocuments(wherestr, (err, result) => {
    if (err) {
      res.send({ status: 500 });
    } else {
      //结果如果有匹配结果则返回条数，否则反0
      res.send({ status: 200, result });
    }
  });
};
function getLocalIP() {
  const interfaces = os.networkInterfaces();
  const addresses = [];
  for (const interfaceName in interfaces) {
    const interfaceObj = interfaces[interfaceName];
    for (const address of interfaceObj) {
      if (address.family === 'IPv4' && !address.internal) {
        addresses.push(address.address);
      }
    }
  }
  return addresses[0] || 'localhost';
}
let localhost = "http://" + getLocalIP() + ":5431";
// 用户验证 用户点击登入，到数据库中匹配数据。
exports.userMatch = (data, pwd, res) => {
  // 因为登入数据可以是邮箱或者手机号码
  let wherestr = { email: data };
  // 匹配成功result后输出项由out控制  1表示输出 0
  let out = { name: 1, imgrul: 1, psw: 1 };
  User.find(wherestr, out, (err, result) => {
    //匹配失败，没有这个用户
    if (err) {
      res.send({ status: 500 });
    } else {
      // 匹配成功后在对密码进行匹配
      //结果为空
      if (result == "") {
        res.send({ status: 400 });
      }
      //把数据库中的密码解密后与用户密码进行匹配
      result.map((item) => {
        //匹配返回是一个promise
        bcrypt.verfication(pwd, item.psw).then((val) => {
          // 密码匹配成功 返回数据中携带token
          //   console.log(val);
          if (val) {
            //用户id生成token
            let token = jwt.generateToken(item._id);
            let back = {
              id: item._id,
              name: item.name,
              imgrul: item.imgrul,
              avtor: localhost+item.imgrul,
              token,
            };
            res.send({ status: 200, back });
          } else {
            // 匹配密码错误
            res.send({ status: 400 });
          }
        });
      });
    }
  });
};

//用户搜索
exports.searchUser = (data, res) => {
  // console.log(data,'data');
  // 设置搜素条件
  let wherestr;
  if (data == "yike31") {
    wherestr = {};
  } else {
    //开启模糊搜索 $regex
    wherestr = {
      $or: [{ name: { $regex: data } }, { email: { $regex: data } }],
    };
  }
  // 设置out输出格式
  let out = { name: 1, email: 1, imgrul: 1 };
  //执行搜索语句，通过res返回给前端
  User.find(wherestr, out, (err, result) => {
    // console.log(result);
    if (err) {
      console.log(err);
      res.send({ status: 500 });
    } else {
      res.send({ status: 200, result });
    }
  });
};

// 判断是否为好友 通过搜索结果数据再次判断是否为好友
exports.isFriend = (uid, fid, res) => {
  let wherestr = { userID: uid, friendID: fid, state: 0 };
  let updatastr = ""; // 查找一条
  Friend.findOne(wherestr, (err, result) => {
    if (err) {
      res.send({ status: 500 });
    } else {
      if (result) {
        res.send({ status: 200 });
      } else {
        //不是好友
        res.send({ status: 400 });
      }
    }
  });
};

// 判断是否为群
exports.searchGroup = (data, res) => {
  let wherestr;
  if (data == "xiaosan") {
    wherestr = {};
  } else {
    //搜群名 $regex
    wherestr = { name: { $regex: data } };
  }
  // 设置out输出格式 群名-群头像
  let out = { name: 1, imgrul: 1 };
  //执行搜索语句，通过res返回给前端
  Group.find(wherestr, out, (err, result) => {
    if (err) {
      res.send({ status: 500 });
    } else {
      res.send({ status: 200, result });
    }
  });
};
//是我是否在群内，显示添加群或进入群聊
exports.isInGroup = (uid, gid, res) => {
  let wherestr = { userId: uid, GroupID: gid };
  // 查找一条
  GroupUser.findOne(wherestr, (err, result) => {
    if (err) {
      res.send({ status: 500 });
    } else {
      // 在群内容
      if (result) {
        res.send({ status: 200 });
      } else {
        //不在群内
        res.send({ status: 400 });
      }
    }
  });
};

// 1新建群 成功得到群id  2 将用户数组群成员表
// 新建群包括 群名 群头像(默认) id 邀请列表（好友id数组）
exports.createGroup = (
  { uid, name, imgrul = "group/group.png", userList },
  res
) => {
  let groupData = {
    // 谁建的裙 裙名 群头像 建群时间
    userID: uid,
    name,
    imgrul,
    time: new Date(),
  };
  let group = new Group(groupData);
  new Promise((resolve, reject) => {
    group.save((err, result_G) => {
      // console.log(result_G._id,'result');
      // 建群失败
      if (err) {
        reject({ staus: 500 });
      } else {
        resolve(result_G);
      }
    });
  })
    .then((val) => {
      // 建群成功 才开始往群内添加新成员
      // 搜索结果显示 群id
      // console.log(val,'val');
      //找到该群的id，往群里插入好友数据
      if (val._id) {
        // 好友数据 数据来自前端。应该是好用id数组(包括群主)
        userList.map((e) => {
          let udata = {
            // 群id
            GroupID: val._id,
            userID: e,
            time: new Date(),
            lastTime: new Date(),
          };
          // 遍历新建数据
          // console.log(udata,'udata');
          this.insertGroupUser(udata);
        });
      }
      //得到群id的，接着添加用户
      res.send({ status: 200 });
    })
    .catch((err) => {
      console.log(err);
    });
};
// 添加群成员
exports.insertGroupUser = (data, res) => {
  let groupuser = new GroupUser(data);
  groupuser.save((err, res) => {
    if (err) {
      res.send({ status: 500 });
    } else {
      console.log("加入成功");
    }
  });
};
// 用户详情
exports.userDetail = (id, res) => {
  let wherestr = { _id: id };
  // pws，控制输出
  let out = { psw: 0 };
  User.findOne(wherestr, out, (err, result) => {
    if (err) {
      res.send({ status: 500 });
    } else {
      res.send({ status: 200, result });
    }
  });
};

//用户的修改 这里的data包括 修改字段 修改类型，修改后的值
function updata(id, updatastr, res) {
  User.findByIdAndUpdate(id, updatastr, (err, result) => {
    if (err) {
      // 修改失败
      res.send({ status: 500, message: "服务器故障" });
    } else {
      // 修改成功
      res.send({ status: 200 });
    }
  });
}
//修改密码为什么没有加密？？？
exports.userUpdata = (data, res) => {
  let updatastr = {};
  //用户输入的旧密码和新密码不能为空
  if (data.type == "psw") {
    //如果修改密码，必须存在长度
    if (data.pwd.length > 0 && data.data.length > 0) {
      // out输出一个密码（hash）
      User.find({ _id: data.id }, { psw: 1 }, (err, result) => {
        if (err) {
          res.send({ status: 500 });
        } else {
          console.log(result, "result");
          result.map((e) => {
            // 根据id找到了用户数据，匹配用户输入的旧密码
            console.log(data.pwd, "data.pwd"); //用户修改密码输入旧密码
            console.log(e.psw, "e.psw"); //数据库中的密码
            // console.log(bcrypt.encryption(e.psw),"加密后的密码")
            // 修改密码前 输入就密码进行比对密码，如果比对成功才更新数据库的密码
            bcrypt.verfication(data.pwd, e.psw).then(
              (val) => {
                console.log(val, "then");
                if (val && data.data.trim().length) {
                  // 如果密码匹配正确，将新密码进行加密然后修改数据库
                  let newpwd = bcrypt.encryption(data.data);
                  updatastr[data.type] = newpwd;
                  console.log(updatastr, "密码修改");
                  // 修改数据库的数据 更具id去更新
                  //  res.send({status:200,title:"接收到修改密码请求"})
                  updata(data.id, updatastr, res);
                } else {
                  // 密码匹配失败
                  console.log("密码不正确");
                  res.send({ status: 400, message: "密码不正确" });
                }
              },
              (err) => {
                console.log(err);
              }
            );
          });
        }
        // res.send({status:400})
      });
    } else {
      res.send({ status: 400, message: "密码不能为空" })
    }
  } else {
    // 因为登入需要使用邮箱/姓名登入，因此需要唯一性
    // 在修改邮箱时，查找数据库中是否存在相同用户邮箱
    if (data.type == "email" || data.type == "name") {
      console.log(data.type, "data.type");
      let wherestr = { $or: [{ email: data.data }, { name: data.data }] };
      User.countDocuments(wherestr, { email: 1, name: 1 }, (err, result) => {
        if (err) {
          // 修改失败
          res.send({ status: 500 });
        } else {
          if (result) {
            // 300表示邮箱以存在
            console.log("邮箱以存在");
            res.send({ status: 300 });
          } else {
            // 邮箱可用 然后进行修改
            // res.send({status:200})
            console.log("邮箱/姓名 可用");
            // data.type 是修改数据类型
            updatastr[data.type] = data.data;
            updata(data.id, updatastr, res);
          }
        }
      });
    } else {
      // data.type 是修改数据类型
      updatastr[data.type] = data.data;
      updata(data.id, updatastr, res);
    }
  }
};

//通过邮箱找到用户id 通过id去修改用户的密码
exports.forgetPsw = (data, res) => {
  console.log(data);
  User.findOne({ email: data.email })
    .then(userRes => {
      // 判断用户是否存在
      if (userRes) {
        //邮箱可能不唯一 需要通过id去查找数据修改
        //加密 
        let pwd = bcrypt.encryption(data.newPwd) 
        let wherestr = { _id: userRes._id } 
        let updatestr = { psw: pwd } 
        //通过id修改用户密码  
        User.updateOne(wherestr, updatestr, (err, result) => { 
          if(err){
            console.log("密码修改失败");
            res.send({ status: 500 })
            return;
          }else{
            console.log("密码修改成功");
            res.send({ status: 200 })
            return;
          }
        })
      }
    }) 
}


// 获取好友昵称
exports.getFriendMarkName = (data, res) => {
  let wherestr = { userID: data.uid, friendID: data.fid };
  Friend.findOne(wherestr, { markname: 1 }, (err, result) => {
    if (err) {
      // 失败
      res.send({ status: 500 });
    } else {
      // 成功 是否存在昵称
      res.send({ status: 200, result });
    }
  });
};

// 修改好友昵称
exports.friendMarkName = (data, res) => {
  let wherestr = { userID: data.uid, friendID: data.fid };
  let updatastr = { markname: data.name };
  Friend.updateOne(wherestr, updatastr, (err, result) => {
    if (err) {
      // 修改失败
      res.send({ status: 500 });
    } else {
      // 修改成功
      res.send({ status: 200 });
    }
  });
};

// 添加好友 就是新建好友
exports.buildFriend = (uid, fid, state, res) => {
  let data = {
    userID: uid,
    friendID: fid,
    state: state,
    //注册时间
    time: new Date(),
    lastTime: new Date(),
  };
  let friend = new Friend(data);
  friend.save((err, result) => {
    if (err) {
      // 修改失败
      console.log("buildFriend添加好友失败");
      // res.send({status:500})
    } else {
      // 修改成功
      console.log("buildFriend添加好友成功");
      // res.send({status:200})
    }
  });
};

// 好友最后通讯时间 或更新请求数据
exports.updataLastTime = ({ uid, fid }) => {
  let wherestr = {
    $or: [
      { userID: uid, friendID: fid },
      { userID: fid, friendID: uid },
    ],
  };
  let updatastr = { lastTime: new Date() };
  // console.log(updatastr);
  Friend.updateMany(wherestr, updatastr, (err, result) => {
    if (err) {
      // 修改失败
      // res.send({status:500})
      console.log("updataLastTime更新LastTime失败");
    } else {
      // 修改成功
      // res.send({status:200})
      console.log("updataLastTime更新LastTime成功");
    }
  });
};

// 添加一对一消息 请求消息是可以多次发送的
exports.insertMsg = (uid, fid, msg, type, res) => {
  let data = {
    userID: uid,
    friendID: fid,
    // 因为message设置为字符串 如果是定位信息对象 需要转换字符串存储 如果是普通文字则不用
    message: type == 3 ? JSON.stringify(msg) : msg,
    types: type,
    time: new Date(),
    state: 1, //消息队列
  };
  console.log(data, "dbserve");
  let message = new Message(data);
  message.save((err, result) => {
    if (err) {
      // 修改失败
      console.log(err, "修改失败");
      res.send({ status: 500 });
    } else {
      console.log(result, "修改成功");

      // 修改成功
      res.send({ status: 200 });
    }
  });
};

// 获取好友申请列表
exports.getApplyList = ({ uid }, res) => {
  // console.log(uid,'uid');
  // 别人向你发申请时，uid是自己，fid是朋友
  // 小明向你申请=> uid:小明，fid：是你 因此别人添加你时你的id是在fid字段
  let wherestr = { friendID: uid, state: 1 };
  Message.find(wherestr, (err, result) => {
    if (err) {
      // 修改失败
      res.send({ status: 500 });
    } else {
      // 修改成功
      res.send({ status: 200, result });
    }
  });
};

// 好友申请  先查找数据库中是否已经是好友，然后进行好友申请
// 第一次提交申请会添加好友申请表中
// 第二次申请时 如果表中存在了数据，修改数据段
exports.applyFirend = (data, res) => {
  let wherestr = { userID: data.uid, friendID: data.fid };
  // 是否已经是好友 匹配返回数据条数
  Friend.countDocuments(wherestr, (err, result) => {
    if (err) {
      // 查找出问题
      res.send({ status: 500 });
    } else {
      // console.log(result,'结果');
      // 初次申请 ！0
      if (!result) {
        // 新建 状态3是发起申请者标识，
        //获取用户申请列表时，只需要查看状态2(申请中)的人
        this.buildFriend(data.uid, data.fid, 3);
        this.buildFriend(data.fid, data.uid, 2);
      } else {
        // 存在申请信息，更新申请时间
        this.updataLastTime(data);
      }
      // 添加一条 一对一请求消息，但是数据库中如果有相同申请是否只需要修改msg实现
      // res.send({result})
      this.insertMsg(data.uid, data.fid, data.msg, 0, res);
    }
  });
};

// 同意好友申请=>更新好友状态 0是好友 1申请中 2申请后未同意
exports.updataFriendState = ({ uid, fid }, res) => {
  // 修改项
  let wherestr = {
    $or: [
      { userID: uid, friendID: fid },
      { userID: fid, friendID: uid },
    ],
  };
  Friend.updateMany(wherestr, { state: 0 }, (err, result) => {
    if (err) {
      // 数据库操作失败
      res.send({ status: 500 });
    } else {
      // 修改成功
      res.send({ status: 200 });
    }
  });
};

// 拒绝或删除好友 ==>修改state
exports.earse = ({ uid, fid }, res) => {
  let wherestr = {
    $or: [
      { userID: uid, friendID: fid },
      { userID: fid, friendID: uid },
    ],
  };
  Friend.deleteMany(wherestr, (err, result) => {
    if (err) {
      // 数据库操作失败
      res.send({ status: 500 });
    } else {
      // 修改成功
      //清空聊天消息
      Message.deleteMany(wherestr, (err, result) => {
        console.log(err);
        // console.log(result);
      });
      res.send({ status: 200 });
    }
  });
};

// 获取好友表数据,在好友表中查找
exports.getUserList = ({ uid, state }, res) => {
  let query = Friend.find({});
  // 在好友表中查找对应的数据
  // console.log(state);
  query.where({ userID: uid, state: state });
  // 关联查询。没搞懂 friendID关联到user表中
  query.populate("friendID");
  // -1逆序 1正序
  query.sort({ lastTime: -1 });
  // 输出
  query
    .exec()
    .then((r) => {
      // 得到结果 过滤数据
      // console.log(r,'过滤数据');
      let result = r.map((item) => {
        return {
          id: item.friendID._id,
          // 关联查询作用
          name: item.friendID.name,
          markname: item.friendID.markname,
          // 没有设置图片则默认为user/user.png 注意这里命名写错了
          imgurl: item.friendID.imgrul || "/user/user.png",
          lastTime: item.lastTime,
        };
      });
      res.send({ status: 200, result });
    })
    .catch((err) => {
      // console.log(err);
      res.send({ status: 500 });
    });
};

// 获取用户最后一条聊天信息
exports.getLastMessage = ({ uid, fid }, res) => {
  // 获取聊天信息
  // console.log(uid,fid,'获取用户最后一条聊天信息');
  let query = Message.findOne({});
  // 在消息表查找对应的数据
  query.where({
    $or: [
      { userID: uid, friendID: fid },
      { userID: fid, friendID: uid },
    ],
  });

  // -1逆序 1正序
  query.sort({ time: -1 });
  // 输出
  query
    .exec()
    .then((r) => {
      // 得到结果 过滤数据
      // console.log(r,'过滤数据');
      let result = {
        message: r.message,
        time: r.time,
        type: r.types,
      };
      res.send({ status: 200, result });
    })
    .catch((err) => {
      console.log(err);
      res.send({ status: 500 });
    });
};

// 消息未读数量 消息数据中的state：1的数量。进行统计
// 消息已读那么状态为state：0
exports.getMsgCountsOfUnread = ({ uid, fid }, res) => {
  // state:1表示未读 作为条件
  let wherestr = { userID: fid, friendID: uid, state: 1 };
  Message.count(wherestr, (err, result) => {
    if (err) {
      res.send({ status: 500 });
    } else {
      if (result) {
        res.send({ status: 200, result });
      } else {
        res.send({ status: 200, result });
      }
    }
  });
};

// 用户查看消息 未读消息数清零  其实就是state：0 =>已读
exports.cleanUnreadMsg_u = ({ uid, fid }, res) => {
  // 这里为什么要反着传，因为消息的关系搞错了
  let wherestr = { userID: fid, friendID: uid, state: 1 };
  console.log(wherestr);
  // 为什么无法修改，数据库中却可以修改
  Message.updateMany(wherestr, { $set: { state: 0 } }, (err, result) => {
    // console.log(result);
    if (err) {
      res.send({ status: 500 });
    } else {
      res.send({ status: 200 });
    }
  });
};

// 群成员表中 uid,查找群  没有验证
exports.getGroupList = ({ uid }, res) => {
  // 获取聊天信息
  let query = GroupUser.find({});
  // 在消息表查找对应的数据
  query.where({ userID: uid });
  // 关联群表 取出群名等信息
  query.populate("GroupID");
  // -1逆序 1正序
  query.sort({ time: -1 });
  // 输出
  query
    .exec()
    .then((r) => {
      // 得到结果 过滤数据
      let result = r.map((item) => {
        return {
          // 关联查询作用
          id: item.GroupID._id,
          name: item.GroupID.name,
          imgrul: item.GroupID.imgrul,
          markname: item.name,
          lastTime: item.lastTime,
          // 未读消息数
          tip: item.tip,
        };
      });
      res.send({ status: 200, result });
    })
    .catch((err) => {
      console.log(err);
      res.send({ status: 500 });
    });
};

// 群聊 获取gid对应群的最后一条消息即可
// 群消息会显示 谁发的：消息。群消息中userID关联到User表，所以我们要关联到user表
exports.getGroupLastMessage = ({ gid }, res) => {
  // 获取聊天信息
  let query = GroupMessage.findOne({});
  // 在消息表查找对应的数据
  query.where({ GroupID: gid });
  // 关联user表
  query.populate("userID");
  // -1逆序 1正序
  query.sort({ time: -1 });
  // 输出
  query
    .exec()
    .then((r) => {
      // 得到结果 过滤数据
      // console.log(r,'过滤数据');
      let result = {
        // 关联到user表
        name: r.userID.name,
        message: r.message,
        time: r.time,
        type: r.types,
      };
      res.send({ status: 200, result });
    })
    .catch((err) => {
      console.log(err);
      res.send({ status: 500 });
    });
};

// 清除未读消息 (前提有该群)用户点击该群，未读消息置空
exports.cleanUnreadMsg_g = ({ uid, gid }, res) => {
  // 群消息表中 根据uid和gid找到群用户，将tip清空
  let wherestr = { userID: uid, GroupID: gid };
  GroupMessage.updateOne(wherestr, { tip: 0 }, (err, result) => {
    if (err) {
      res.send({ status: 500 });
    } else {
      res.send({ status: 200 });
    }
  });
};

// 分页获取一对一消息操作
// uid fid nowpage pageSize
exports.getMessagePage = ({ uid, fid, nowPage = 0, pageSize = 0 }, res) => {
  //跳过多少条数据
  var skipNum = nowPage + pageSize;
  let query = Message.find({});
  // 聊天数据
  query.where({
    $or: [
      { userID: uid, friendID: fid },
      { userID: fid, friendID: uid },
    ],
  });
  // -1逆序 1正序
  query.sort({ time: -1 });

  // 关联查询。没搞懂 friendID关联到user表中
  query.populate("userID");
  // 跳过多少条数据
  query.skip(skipNum);
  // 一页数据的条数
  query.limit(pageSize);
  // 输出
  query
    .exec()
    .then((r) => {
      // 得到结果 过滤数据
      // console.log(r,'过滤数据');
      let result = r.map((item) => {
        return {
          // 聊天数据的id
          id: item._id,
          message: item.message,
          types: item.types,
          time: item.time,
          // 数据关联性
          // 数据来自谁/头像
          fromId: item.userID._id,
          imgurl: item.userID.imgrul,
        };
      });
      res.send({ status: 200, result });
    })
    .catch((err) => {
      // console.log(err);
      res.send({ status: 500 });
    });
};
